package com.uxsino.simo.indicator.retractor;

import com.uxsino.commons.utils.config.ConfigProp;
import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryContext;
import com.uxsino.simo.query.QueryTemplate;
import org.apache.commons.collections4.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
example input:
OK - Number of results: 5

Name: java.lang:type=MemoryPool,name=Eden Space
modelerType: sun.management.MemoryPoolImpl
PeakUsage: javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=java.lang.management.MemoryUsage,items=((itemName=committed,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=init,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=max,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=used,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)))),contents={committed=9502720, init=4390912, max=139853824, used=9502720})
MemoryManagerNames: Array[java.lang.String] of length 2
    MarkSweepCompact
    Copy
UsageThresholdSupported: false
CollectionUsageThreshold: 0
CollectionUsageThresholdExceeded: false
CollectionUsageThresholdCount: 0
CollectionUsage: javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=java.lang.management.MemoryUsage,items=((itemName=committed,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=init,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=max,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=used,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)))),contents={committed=9502720, init=4390912, max=139853824, used=0})
CollectionUsageThresholdSupported: true
Name: Eden Space
Type: HEAP
Valid: true
Usage: javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=java.lang.management.MemoryUsage,items=((itemName=committed,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=init,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=max,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=used,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)))),contents={committed=9502720, init=4390912, max=139853824, used=8569960})
ObjectName: java.lang:type=MemoryPool,name=Eden Space

Name: java.lang:type=MemoryPool,name=Code Cache
modelerType: sun.management.MemoryPoolImpl
...
*/
public class TomcatMemPoolRetracor extends ListValueRetractor {
    private static Logger logger = LoggerFactory.getLogger(TomcatMemPoolRetracor.class);

    @ConfigProp(name = "skip_row")
    public String skipRow;

    @ConfigProp(name = "col_delimiter")
    public String colDelimiter;

    @ConfigProp(name = "row_delimiter")
    public String rowDelimiter;

    @ConfigProp(name = "item_delimiter")
    public String itemDelimiter;

    public TomcatMemPoolRetracor() {
        super();
        colDelimiter = ":";
        skipRow = "1";
        rowDelimiter = "((\\n\\r)|(\\r\\n)){1}|(\\r){1}|(\\n){1}";
        itemDelimiter = "((\\n\\r)|(\\r\\n)){2}|(\\r){2}|(\\n){2}";
    }

    @Override
    public Object doRetract(EntityInfo entity, QueryContext ctxt, QueryTemplate qt, Object obj) {
        List<Map<String, Object>> result = new ArrayList<>();
        if (obj == null) {
            logger.error("retract object is null");
            return null;
        }
        String[] strArr = ((String) obj).split(itemDelimiter);
        for (int i = 0; i < strArr.length; i++) {
            Map<String, Object> mp = new HashedMap<>();
            if (i == 0) {
                continue;
            }
            String[] lines = strArr[i].split(rowDelimiter);
            for (ColumnEntry entry : columnEntries) {
                String fieldName = entry.field.getName();
                String[] strs = fieldName.split("_");
                if (strs != null && strs.length < 3) {
                    logger.error("field_name's format is wrong, **_**_**..");
                    return null;
                }
                String keyName = strs[2];

                for (String line : lines) {
                    if (!line.contains(":")) {
                        continue;
                    }
                    String[] kv = line.split(":");
                    if (keyName != null && kv.length == 2 && keyName.equalsIgnoreCase(kv[0])) {
                        String regex = entry.regexPattern;
                        if (!(regex == null || regex.equals(""))) {
                            Pattern pattern = Pattern.compile(regex);
                            Matcher mat = pattern.matcher((String) kv[1]);
                            mp.put(fieldName, mat.find() ? mat.group(1) : "0");
                        } else {
                            mp.put(fieldName, (kv[1]).substring(1));
                        }
                        break;
                    }
                }
            }
            result.add(mp);
        }
        return result;
    }

}
